package com.corner.web.controller.system;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import com.corner.common.annotation.RepeatSubmit;
import com.corner.common.constant.CacheConstants;
import com.corner.common.constant.HttpStatus;
import com.corner.common.core.domain.entity.Role;
import com.corner.common.core.domain.model.LoginUser;
import com.corner.common.core.redis.RedisCache;
import com.corner.common.exception.GlobalException;
import com.corner.common.utils.uuid.IdUtils;
import com.corner.framework.manager.AsyncManager;
import com.corner.framework.manager.factory.AsyncFactory;
import com.corner.framework.web.service.TokenService;
import com.corner.system.domain.FarmerUser;
import com.corner.system.mapper.FarmerUserMapper;
import com.corner.system.mapper.SysUserMapper;
import com.corner.system.service.AliMessageService;
import com.corner.system.service.DeviceService;
import com.corner.system.service.WxgzhService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.*;
import com.corner.common.constant.Constants;
import com.corner.common.core.domain.AjaxResult;
import com.corner.common.core.domain.entity.SysMenu;
import com.corner.common.core.domain.entity.SysUser;
import com.corner.common.core.domain.model.LoginBody;
import com.corner.common.utils.SecurityUtils;
import com.corner.framework.web.service.SysLoginService;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

/**
 * 登录验证
 * 
 * @author corner
 */
@Slf4j
@RestController
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;
    @Autowired
    private WxgzhService wxgzhService;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private FarmerUserMapper farmerUserMapper;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private AliMessageService messageService;

    @Value("${ALI_MESSAGE.SIGN_NAME}")
    public String SIGN_NAME;
    @Value("${ALI_MESSAGE.TEMPLATE_CODE}")
    public String TEMPLATE_CODE;
    @Value("${ALI_MESSAGE.TEMPLATE_PARAM}")
    public String TEMPLATE_PARAM;



    /**
     * 登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login/{wxcode}")
    public AjaxResult login(@RequestBody LoginBody loginBody,@PathVariable(name = "wxcode") String wxcode)
    {
        AjaxResult ajax = AjaxResult.success();

        SysUser loginUser = null;

        Map tokenAndUid = null;

        //查看登录人是否为审核人
        Boolean isAdmin = false;
        String username = loginBody.getUsername();
        if(StringUtils.isBlank(username)){
            throw new GlobalException("请输入用户名或手机号");
        }
        SysUser user = userMapper.selectUserByUserName(username);
        if(user != null){
            List<Role> roles = user.getRoles();
            if(roles != null && roles.size() > 0){
                for(Role r: roles){
                    String roleKey = r.getRoleKey();
                    if("funds_audit".equals(roleKey)||"admin".equals(roleKey)||"test_user".equals(roleKey)){
                        isAdmin = true;
                        break;
                    }
                }
            }
        }

        //如果不是审核员，需要校验
        if(!isAdmin){

            loginService.validateCaptcha(loginBody.getUsername(), loginBody.getCode(), loginBody.getUuid());

            //查看用户是否关注公众号

            try {
                //测试数据
                String openid = null;
                /*if("13163679357".equals(loginBody.getUsername())){
                    openid = "oyl1k6MUIQK43De_Q47ItJmC8ERY";
                }else{

                }*/
                Map<String, String> urlAccessToken = wxgzhService.getUrlAccessToken(wxcode,username);
                openid = urlAccessToken.get("openid");
                if(openid == null){
                    throw new GlobalException("无法获取OPENID");
                }
                //用户是否已关注公众号
                loginUser = userMapper.selectByOpenId(openid);
                if(loginUser == null ){
                    System.out.println(openid);
                    throw new GlobalException("请先关注公众号");
                }

                //查询设备表中是否有该手机号
                FarmerUser query = new FarmerUser();
                query.setTelephone(loginBody.getUsername());
                List<FarmerUser> farmerUserList = farmerUserMapper.selectFarmerUser(query);
                if(farmerUserList == null || farmerUserList.size() == 0){
                    throw new GlobalException("未查询到此手机号码");
                }

                // 如果未绑定手机号，先校验这个手机号是否已经被其他人绑定
                if (user != null && !user.getOpenId().equals(openid)){

                    //将上一个登录此手机号的用户名置空
                    user.setUserName("");
                    userMapper.updateUser(user);
                }

                // 需要将手机号和用户名更新到user表中
                loginUser.setUserName(loginBody.getUsername());
                loginUser.setTelephoneNumber(loginBody.getUsername());
                //sysUserByOpenId.setPassword(SecurityUtils.encryptPassword(loginBody.getPassword()));
                userMapper.updateUser(loginUser);

                // 生成令牌
                tokenAndUid = loginService.login(loginBody,loginUser);
            } catch (GlobalException e) {
                e.printStackTrace();
                throw new GlobalException(e.getMessage(),HttpStatus.LOGIN_REFRESH_FAIL);
            }


        }else{
            // 生成令牌
            tokenAndUid = loginService.loginOld(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                    loginBody.getUuid(),loginBody.getIsPhone());

        }

        ajax.put("loginResultMap", tokenAndUid);
        return ajax;
    }


    /**
     * 测试登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/loginNoCheck/{wxcode}")
    public AjaxResult loginNoCheck(@RequestBody LoginBody loginBody,@PathVariable(name = "wxcode") String wxcode)
    {
        AjaxResult ajax = AjaxResult.success();

        SysUser loginUser = null;

        Map tokenAndUid = null;

        //查看登录人是否为审核人
        Boolean isAdmin = false;
        String username = loginBody.getUsername();
        SysUser user = userMapper.selectUserByUserName(username);
        if(user != null){
            List<Role> roles = user.getRoles();
            if(roles != null && roles.size() > 0){
                for(Role r: roles){
                    String roleKey = r.getRoleKey();
                    if("funds_audit".equals(roleKey)||"admin".equals(roleKey)||"test_user".equals(roleKey)){
                        isAdmin = true;
                        break;
                    }
                }
            }
        }

        //如果不是审核员，需要校验
        if(!isAdmin){
            //loginService.validateCaptcha(loginBody.getUsername(), loginBody.getCode(), loginBody.getUuid());

            //查看用户是否关注公众号

            try {
                //测试数据
                String openid = "oyl1k6MUIQK43De_Q47ItJmC8ERY";

                //用户是否已关注公众号
                loginUser = userMapper.selectByOpenId(openid);
                if(loginUser == null ){
                    System.out.println(openid);
                    throw new GlobalException("请先关注公众号");
                }

                //查询设备表中是否有该手机号
                FarmerUser query = new FarmerUser();
                query.setTelephone(loginBody.getUsername());
                List<FarmerUser> farmerUserList = farmerUserMapper.selectFarmerUser(query);
                if(farmerUserList == null || farmerUserList.size() == 0){
                    throw new GlobalException("未查询到此手机号码");
                }

                // 如果未绑定手机号，先校验这个手机号是否已经被其他人绑定
                if (user != null && !user.getOpenId().equals(openid)){
                    user.setUserName("");
                    userMapper.updateUser(user);
                }

                // 需要将手机号和用户名更新到user表中
                loginUser.setUserName(loginBody.getUsername());
                loginUser.setTelephoneNumber(loginBody.getUsername());
                //sysUserByOpenId.setPassword(SecurityUtils.encryptPassword(loginBody.getPassword()));
                userMapper.updateUser(loginUser);

                // 生成令牌
                tokenAndUid = loginService.login(loginBody,loginUser);
            } catch (GlobalException e) {
                e.printStackTrace();
                throw new GlobalException(e.getMessage(),HttpStatus.LOGIN_REFRESH_FAIL);
            }


        }else{
            // 生成令牌
            tokenAndUid = loginService.loginOld(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                    loginBody.getUuid(),loginBody.getIsPhone());

        }

        ajax.put("loginResultMap", tokenAndUid);
        return ajax;
    }


    /**
     * 登录方法
     * 
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/loginOld/{code}")
    public AjaxResult loginOld(@RequestBody LoginBody loginBody,@PathVariable(name = "code") String code)
    {
        AjaxResult ajax = AjaxResult.success();

        //查看登录人是否为审核人
        Boolean isAdmin = false;
        String username = loginBody.getUsername();
        SysUser user = userMapper.selectUserByUserName(username);
        if(user != null){
            List<Role> roles = user.getRoles();
            if(roles != null && roles.size() > 0){
                for(Role r: roles){
                    String roleKey = r.getRoleKey();
                    if("funds_audit".equals(roleKey)||"admin".equals(roleKey)||"test_user".equals(roleKey)){
                        isAdmin = true;
                        break;
                    }
                }
            }
        }

        //如果不是审核员，需要校验
        if(!isAdmin){
            //查看用户是否关注公众号
            //获取openid
            Map<String, String> urlAccessToken = wxgzhService.getUrlAccessToken(code,username);
            String openid = urlAccessToken.get("openid");
            if(openid == null){
                throw new RuntimeException("无OPENID");
            }
            //测试数据
            //String openid = "oyl1k6MUIQK43De_Q47ItJmC8ERY";
            //用户是否已关注公众号
            SysUser sysUserByOpenId = userMapper.selectByOpenId(openid);
            if(sysUserByOpenId == null ){
                throw new RuntimeException("请先关注公众号");
            }



            // 查看用户是否已经绑定手机号和农户id
            if(StringUtils.isBlank(sysUserByOpenId.getUserName())){
                //没有登录过
                //查询设备表中是否有该手机号
                FarmerUser query = new FarmerUser();
                query.setTelephone(loginBody.getUsername());
                List<FarmerUser> farmerUserList = farmerUserMapper.selectFarmerUser(query);
                if(farmerUserList == null || farmerUserList.size() == 0){
                    throw new RuntimeException("未查询到此手机号码");
                }
                // 如果未绑定手机号，先校验这个手机号是否已经被其他人绑定
                if (user != null && !user.getOpenId().equals(openid)){
                    throw new RuntimeException("该手机号以被其他微信账号绑定");
                }
                // 需要将手机号和用户名更新到user表中
                sysUserByOpenId.setUserName(loginBody.getUsername());
                //sysUser.setFarmerId(farmerUser.getFarmerId());
                sysUserByOpenId.setTelephoneNumber(loginBody.getUsername());
                sysUserByOpenId.setPassword(SecurityUtils.encryptPassword(loginBody.getPassword()));
                userMapper.updateUser(sysUserByOpenId);
            }else{
                // 已经绑定手机号了
                // 校验手机号与原绑定号是否一致
                if(!sysUserByOpenId.getUserName().equals(loginBody.getUsername())){
                    throw new GlobalException("您输入的手机号有误，如需更改，请登陆后在用户中心申请修改");
                }
            }

        }

        // 生成令牌
        Map tokenAndUid = loginService.loginOld(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid(),loginBody.getIsPhone());

        ajax.put("loginResultMap", tokenAndUid);
        return ajax;
    }


    /**
     * 用户点击发送短信验证码
     * @return
     */
    @RepeatSubmit
    @PostMapping("/sendMessageCaptchaCode/{tel}")
    public AjaxResult sendMessageCaptchaCode(@PathVariable(name = "tel") String tel)throws Exception{
        System.out.println("调用短信验证码:"+tel);
        // 保存验证码信息
        String uuid = IdUtils.simpleUUID();
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + tel + uuid;

        // 生成4位数字验证码
        String code = generateVerificationCode();

        redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);

        // 调用短信api
        String content = String.format(TEMPLATE_PARAM,code);
        String replace = content.replace("^", "");
        messageService.sendMessage(SIGN_NAME, TEMPLATE_CODE, tel, replace);

        AjaxResult ajax = AjaxResult.success();
        ajax.put("uuid", uuid);
        //ajax.put("img", Base64.encode(os.toByteArray()));
        return ajax;
    }





    /**
     * 生成随机4位数字
     * @return
     */
    private String generateVerificationCode() {
        Random random = new Random();
        StringBuilder sb = new StringBuilder(4);
        for (int i = 0; i < 4; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }



    /**
     * @method 检查后端登录状态
     * @description
     * @date: 2021-12-8 14:05
     * @author: chenhenan
     * @param
     * @return
     */
    @GetMapping("/checkLoginStatus")
    public AjaxResult checkLoginStatus(HttpServletRequest request){
        LoginUser loginUser = tokenService.getLoginUser(request);
        if(loginUser == null){
            throw new GlobalException("用户未授权", HttpStatus.UNAUTHORIZED);
        }
        return AjaxResult.success("用户已登录");
    }


    @RequestMapping("/logofUser")
    public AjaxResult logofUser(){
        log.info("退出登录");
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (com.corner.common.utils.StringUtils.isNotNull(loginUser)) {
            String userName = loginUser.getUsername();
            // 删除用户缓存记录
            tokenService.delLoginUser(loginUser.getToken());
            // 记录用户退出日志
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功"));
        }
        return AjaxResult.success("用户已登出");
    }


    /**
     * 获取用户信息
     * 
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();

        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);

        return ajax;
    }


}
